package com.sprouting.personal.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.DES;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sprouting.personal.annotations.ApiIdempotent;
import com.sprouting.personal.interfaces.common.CacheKey;
import com.sprouting.personal.interfaces.common.Constant;
import com.sprouting.personal.interfaces.common.ConstantMsg;
import com.sprouting.personal.interfaces.common.ConstantPath;
import com.sprouting.personal.model.common.ResultJson;
import com.sprouting.personal.model.common.jsr.AddGroup;
import com.sprouting.personal.model.common.jsr.UpdGroup;
import com.sprouting.personal.model.entity.*;
import com.sprouting.personal.model.vo.LunarVo;
import com.sprouting.personal.model.vo.MemberFamilyTree;
import com.sprouting.personal.model.vo.MemberFamilyVo;
import com.sprouting.personal.service.*;
import com.sprouting.personal.utils.CheckTool;
import com.sprouting.personal.utils.DateTool;
import com.sprouting.personal.utils.EntityTool;
import com.sprouting.personal.utils.IdTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户控制层
 *
 * @author ：LX（长沙麓谷）
 * @date 创建时间： 2022/7/27 0:13
 */
@RequestMapping("/user")
@RestController
@Slf4j
public class UserController {

    @Autowired
    private UserService userService;
    @Autowired
    private MemberFamilyService memberFamilyService;
    @Autowired
    private JoinService joinService;
    @Autowired
    private DictService dictService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private UploadFileService uploadFileService;

    /**
     * 上传图片类型
     */
    @Value("#{'${upload.image.type}'.split(',')}")
    private List<String> uploadImageTypeList;
    /**
     * 图片文件上传最大长度
     */
    @Value("${upload.image.max.length}")
    private Integer uploadImageMaxLength;
    /**
     * 系统登录加密解密的key
     */
    @Value("${login.password.key}")
    private String loginPasswordKey;
    /**
     * 文件存储基础路径
     */
    @Value("${upload.data.base.path}")
    private String basePath;


    /**
     * 获取可迁移的目标用户
     * @param userId 用户ID,用来过滤的参数
     * @return
     */
    @PostMapping(value = "getTransfer")
    public ResultJson getTransfer(String userId){
        if (CheckTool.checkNull(userId)){
            return ResultJson.errorIllegal();
        }
        // 不能是自己的子级，不能是自己
        List<MemberFamilyTree> tree = getTree(StpUtil.getLoginIdAsString());
        if (CollUtil.isEmpty(tree)){
            return ResultJson.success();
        }

        // 找到当前用户，将它以及下级全部切掉
        delThisNode(tree, userId);
        if (CollUtil.isEmpty(tree)){
            return ResultJson.success();
        }

        // 遍历出剩下的数据
        List<MemberFamilyTree> userList = new ArrayList<>();
        getTransferUser(userList, tree);
        return ResultJson.success(userList);
    }

    /**
     * 迁移数据用户到另外一个用户下面
     * @param userId 要迁移数据人的ID
     * @param sourceId 迁移的目标
     * @return
     */
    @PostMapping("migrate")
    public ResultJson migrate(String userId, String sourceId){
        // 应该校验下相关数据，比如目标是否回环，是否本系统的数据，但这里暂不考虑这种情况
        if (CheckTool.checkNull(userId, sourceId)){
            return ResultJson.errorIllegal();
        }
        MemberFamily memberFamily = memberFamilyService.getMemberFamilyById(sourceId);
        if (memberFamily == null){
            return ResultJson.errorPram();
        }

        // 要变迁的数据
        Join join = joinService.getJoinByTargetId(userId);
        join.setSourceId(sourceId);
        joinService.updateById(join);
        return ResultJson.success();
    }

    /**
     * 登出，只登出当前设备的
     * @return
     */
    @PostMapping("/logout")
    public ResultJson logout(){
        String tokenDevice = StpUtil.getLoginDevice();
        StpUtil.kickout(StpUtil.getLoginIdAsString(), tokenDevice);
        return ResultJson.success(ConstantMsg.SUCCESS_MSG);
    }

    /**
     * 修改自身的密码
     * @param old 旧的密码
     * @param news 新的密码
     * @return
     */
    @ApiIdempotent
    @PostMapping("/updPassword")
    public ResultJson updPassword(String old, String news){
        if (CheckTool.checkNull(old) || CheckTool.checkNull(news)){
            return ResultJson.errorIllegal();
        }

        old = old.trim();
        news = news.trim();

        try {
            DES des = SecureUtil.des(loginPasswordKey.getBytes(Constant.Encoded.UTF));
            old = des.decryptStr(old);
            news = des.decryptStr(news);
        } catch (Exception e) {
            log.error("[修改密码] 对新密码或旧密码解密错误，新密码：{}，旧密码：{}", news, old);
            return ResultJson.error(ConstantMsg.ERROR_MSG_ILLEGAL_REQUEST);
        }

        // 修改自身的密码
        SaSession session = StpUtil.getSession(true);
        User user = session.getModel(CacheKey.SaTokenSession.SESSION_KEY_USER, User.class);
        // todo 应该进行加密，但这小系统不做复杂，防止忘记密码的事情
        // String passwordOld = SaSecureUtil.md5BySalt(old, user.getSalt());
        String passwordOld = old;
        if (!user.getPassword().equals(passwordOld)){
            return ResultJson.error("旧密码错误");
        }

        // String passwordNews = SaSecureUtil.md5BySalt(news, user.getSalt());
        String passwordNews = news;
        user.setPassword(passwordNews);
        user.setUpdateTime(new Date());
        userService.updateById(user);
        return ResultJson.success(null);
    }

    /**
     * 获取社交关系类型选项
     * @param type 1，只获取家庭成员2，获取社交关系，3，1+2全部获取
     * @return
     */
    @PostMapping("/getSocialConnectionType")
    public ResultJson<List<Dict>> getSocialConnectionType(Integer type){
        if (type.equals(1)){
            // 家庭成员
            return ResultJson.success(dictService.getType(Constant.RetainDictGroup.MEMBER_OF_FAMILY, StpUtil.getLoginIdAsString()));

        } else if (type.equals(2)){
            // 社交关系
            return ResultJson.success(dictService.getType(Constant.RetainDictGroup.SOCIAL_NETWORKS_GROUP, StpUtil.getLoginIdAsString()));

        } else {
            // 全部
            List<Dict> dictList = new ArrayList<>();
            List<Dict> memberList = dictService.getType(Constant.RetainDictGroup.MEMBER_OF_FAMILY, StpUtil.getLoginIdAsString());
            List<Dict> socialNetworksList = dictService.getType(Constant.RetainDictGroup.SOCIAL_NETWORKS_GROUP, StpUtil.getLoginIdAsString());

            if (CollUtil.isNotEmpty(memberList)){
                dictList.addAll(memberList);
            }
            if (CollUtil.isNotEmpty(socialNetworksList)){
                dictList.addAll(socialNetworksList);
            }
            return ResultJson.success(dictList);
        }
    }

    /**
     * 根据主键查询用户ID
     * @param id 用户ID
     * @return
     */
    @PostMapping("/getMemberFamilyById")
    public ResultJson getMemberFamilyById(String id){
        if (CheckTool.checkNull(id)){
            id = StpUtil.getLoginIdAsString();
        }

        return ResultJson.success(memberFamilyService.getMemberFamilyById(id));
    }

    /**
     * 根据用户名查询用户信息
     * @param userName 用户名
     * @return
     */
    @PostMapping("/getUserByUserName")
    public ResultJson getUserByUserName(String userName){
        if (CheckTool.checkNull(userName)){
            // 返回成功，防止误触发
            return ResultJson.success();
        }
        MemberFamily memberFamilyDb = memberFamilyService.getMemberFamilyRepeatQuery(null, StpUtil.getLoginIdAsString(), userName);
        return ResultJson.success(memberFamilyDb);
    }

    /**
     * 根据身份证查询用户信息
     * @param idCard 身份证
     * @return
     */
    @PostMapping("/getUserByIdCard")
    public ResultJson getUserByIdCard(String idCard){
        if (CheckTool.checkNull(idCard)){
            // 返回成功，防止误触发
            return ResultJson.success();
        }
        MemberFamily memberFamilyDb = memberFamilyService.getMemberFamilyByIdCard(null, StpUtil.getLoginIdAsString(), idCard);
        return ResultJson.success(memberFamilyDb);
    }

    /**
     * 根据主键查询用户，与上面的方法相比，会将一些关联信息查询出来
     * @param id 用户ID
     * @return
     */
    @PostMapping("/getMemberFamilyByIdJoin")
    public ResultJson getMemberFamilyByIdJoin(String id){
        if (CheckTool.checkNull(id)){
            id = StpUtil.getLoginIdAsString();
        }

        if (id.equals(StpUtil.getLoginIdAsString())){
            // 是本人的时候，直接查询用户表，否则查询不到数据
            return ResultJson.success(getMemberFamilyThis());

        } else {
            MemberFamilyVo memberFamilyVo = memberFamilyService.getMemberFamilyByIdJoin(id);

            MemberFamilyVo parent = memberFamilyService.getMemberFamilyByIdJoin(memberFamilyVo.getSourceId());
            if (parent != null){
                memberFamilyVo.setParent(parent);
                return ResultJson.success(memberFamilyVo);
            } else {
                // 查到的最高级别的数据
                memberFamilyVo.setParent(getMemberFamilyThis());
                return ResultJson.success(memberFamilyVo);
            }
        }
    }

    /**
     * 获取上传的用户照片
     * @param memberFamilyId 人员ID
     * @return
     */
    @PostMapping("/getMemberFamilyPicture")
    public ResultJson getMemberFamilyPicture(String memberFamilyId){
        if (CheckTool.checkNull(memberFamilyId)){
            return ResultJson.errorIllegal();
        }
        return ResultJson.success(uploadFileService.getUploadFileByBindingIdNotTemp(memberFamilyId));
    }

    /**
     * 调用延迟删除成员照片
     * @param uploadFileId 上传信息ID
     * @return
     */
    @PostMapping("/delMemberFamilyPicture")
    @ApiIdempotent
    public ResultJson delMemberFamilyPicture(String uploadFileId){
        if (CheckTool.checkNull(uploadFileId)){
            return ResultJson.errorIllegal();
        }
        UploadFile uploadFile = uploadFileService.getUploadFileById(uploadFileId);
        if (uploadFile == null){
            return ResultJson.errorPram();
        }

        // 将照片设置为临时照片，让定时任务去处理删除
        uploadFile.setTempFile(Constant.TempFile.TEMP);
        uploadFileService.updateById(uploadFile);
        return ResultJson.success();
    }

    /**
     * 保存成员的照片
     * @param multipartFile 照片
     * @param memberFamilyId 成员ID {@link MemberFamily#getId()}
     * @return
     */
    @ApiIdempotent
    @PostMapping("/saveMemberFamilyPicture")
    public ResultJson saveMemberFamilyPicture(@RequestParam(value = "file", required = false) MultipartFile multipartFile, String memberFamilyId){
        if (CheckTool.checkNull(memberFamilyId)){
            return ResultJson.errorIllegal();
        }
        if (multipartFile == null){
            return ResultJson.error("请上传文件");
        }
        String originalFilename = multipartFile.getOriginalFilename();
        if (CheckTool.checkNull(originalFilename)){
            return ResultJson.error("获取文件名失败");
        }
        String suffix = FileUtil.getSuffix(originalFilename).toLowerCase();
        if (CheckTool.checkNull(suffix)){
            // 检查特殊情况下的文件名不符合
            return ResultJson.error("非法上传图片名，不支持的后缀");
        }
        if (uploadImageTypeList != null){
            if (!uploadImageTypeList.contains(suffix)){
                return ResultJson.error("上传图片类型不支持");
            }
        }
        if (multipartFile.getSize() > uploadImageMaxLength){
            return ResultJson.error("上传图片超过限定大小");
        }
        MemberFamily memberFamily = memberFamilyService.getMemberFamilyById(memberFamilyId);
        if (memberFamily == null){
            return ResultJson.errorPram();
        }

        String path = String.format(ConstantPath.Path.SOCIAL_CIRCLE_USER_ICO,
                basePath, StpUtil.getLoginIdAsString(), memberFamilyId, IdTool.getId(), suffix);
        File toFile = new File(path);

        // 上传路径
        if (!FileUtil.exist(toFile)){
            FileUtil.touch(toFile);
        }

        try {
            multipartFile.transferTo(toFile);
        } catch (IOException e) {
            log.error("图片上传失败", e);
            return ResultJson.error("图片上传失败");
        }

        // 只保存相对路径
        String replacePath = path.replace(basePath, "");

        UploadFile uploadFile = new UploadFile();
        uploadFile.setId(IdTool.getId());
        uploadFile.setUserId(StpUtil.getLoginIdAsString());
        uploadFile.setBindingId(memberFamilyId);
        uploadFile.setFileType(Constant.FileType.IMG);
        uploadFile.setSavePath(replacePath);
        uploadFile.setType(Constant.FileSourceType.SOCIAL_CIRCLE_USER);
        uploadFile.setDelResource(Constant.YesOrNo.NO);
        uploadFile.setTempFile(Constant.TempFile.PRODUCTION);
        EntityTool.buildSaveBase(uploadFile, StpUtil.getLoginIdAsString());
        uploadFileService.save(uploadFile);
        return ResultJson.success();
    }

    /**
     * 添加家庭成员|社会关系
     * @param memberFamily 家庭成员信息
     * @param file 家庭成员照片
     * @param join 关系
     * @return
     */
    @ApiIdempotent
    @PostMapping("/saveMemberFamily")
    public ResultJson saveMemberFamily(@Validated(AddGroup.class) MemberFamily memberFamily, @Validated(AddGroup.class) Join join,
                                       @RequestParam(value = "file", required = false) MultipartFile file,
                                       @RequestParam(value = "tombFile", required = false) MultipartFile tombFile,
                                       @RequestParam(value = "hometownFile", required = false) MultipartFile hometownFile){
        String msg = idCardSupplement(memberFamily);
        if (msg != null){
            return ResultJson.error(msg);
        }

        String err = checkMemberFamily(memberFamily);
        if (err != null){
            return ResultJson.error(err);
        }
        // 补充提前多久提醒生日
        if (memberFamily.getBeforeBirthday() == null){
            Config config = configService.getConfigByCodeAutomaticCompletion(Constant.ConfigCode.BIRTHDAY_REMINDER, StpUtil.getLoginIdAsString());
            if (CheckTool.checkNull(config.getValue())){
                // 默认提前七天
                memberFamily.setBeforeBirthday(7);
            } else {
                memberFamily.setBeforeBirthday(Integer.valueOf(config.getValue()));
            }
        }
        if (CheckTool.checkNull(memberFamily.getUserName())){
            memberFamily.setUserName(Constant.DefaultValue.UNKNOWN_NAME);
        }

        // 上传图片
        String errFile = userIcoUpload(file, tombFile, hometownFile, memberFamily);
        if (errFile != null){
            return ResultJson.error(errFile);
        }

        memberFamily.setId(IdTool.getId());
        memberFamily.setUserId(StpUtil.getLoginIdAsString());
        EntityTool.buildSaveBase(memberFamily, StpUtil.getLoginIdAsString());

        join.setId(IdTool.getId());
        join.setUserId(StpUtil.getLoginIdAsString());
        if(CheckTool.checkNull(join.getSourceId())){
            // 说明是家庭成员
            join.setSourceId(StpUtil.getLoginIdAsString());
            // 如果是家庭成员，排序要在前面，默认给增加一点排序到前面
            if (!Constant.DefaultValue.SORT.equals(memberFamily.getSort())){
                memberFamily.setSort(memberFamily.getSort() - 10);
            }

        } else {
            // 说明是非家庭成员
        }

        join.setTargetId(memberFamily.getId());
        EntityTool.buildSaveBase(join, StpUtil.getLoginIdAsString());

        memberFamilyService.saveMemberFamily(memberFamily, join);
        return ResultJson.success();
    }

    /**
     * 更新家庭成员信息
     * @param memberFamily 家庭成员信息
     * @param join 关系
     * @param file 上传的头像信息
     * @param joinId 关系表ID，防止和成员表ID冲突
     * @return
     */
    @PostMapping("/updMemberFamily")
    @ApiIdempotent
    public ResultJson updMemberFamily(@Validated(UpdGroup.class) MemberFamily memberFamily, @Validated(AddGroup.class) Join join, String joinId,
                                      @RequestParam(value = "file", required = false) MultipartFile file,
                                      @RequestParam(value = "tombFile", required = false) MultipartFile tombFile,
                                      @RequestParam(value = "hometownFile", required = false) MultipartFile hometownFile){
        String msg = idCardSupplement(memberFamily);
        if (msg != null){
            return ResultJson.error(msg);
        }
        String err = checkMemberFamily(memberFamily);
        if (err != null){
            return ResultJson.error(err);
        }
        if (CheckTool.checkNull(joinId)){
            return ResultJson.errorIllegal();
        }

        MemberFamily memberFamilyDb = memberFamilyService.getMemberFamilyById(memberFamily.getId());
        // 上传图片
        String errFile = userIcoUpload(file, tombFile, hometownFile, memberFamily);
        if (errFile != null){
            return ResultJson.error(errFile);
        }

        if (CheckTool.checkNull(memberFamily.getUserName())){
            memberFamily.setUserName(Constant.DefaultValue.UNKNOWN_NAME);
        }

        EntityTool.buildUpdBase(memberFamily, StpUtil.getLoginIdAsString());
        // 防止篡改
        join.setId(joinId);
        join.setUserId(null);
        join.setSourceId(null);
        join.setTargetId(null);
        EntityTool.buildUpdBase(join, StpUtil.getLoginIdAsString());
        memberFamilyService.updMemberFamily(memberFamily, join);

        // 清理图片
        delUserIco(memberFamilyDb, file, tombFile, hometownFile);

        return ResultJson.success();
    }

    /**
     * 更新主用户
     * @param memberFamily 登录用户信息
     * @param file 上传的头像信息
     * @param tombFile 陵墓图片
     * @param hometownFile 老家图片
     * @return
     */
    @PostMapping("/updateUser")
    @ApiIdempotent
    public ResultJson updateUser(@Validated(UpdGroup.class) MemberFamily memberFamily,
                                 @RequestParam(value = "file", required = false) MultipartFile file,
                                 @RequestParam(value = "tombFile", required = false) MultipartFile tombFile,
                                 @RequestParam(value = "hometownFile", required = false) MultipartFile hometownFile){
        String msg = idCardSupplement(memberFamily);
        if (msg != null){
            return ResultJson.error(msg);
        }
        String err = checkMemberFamily(memberFamily);
        if (err != null){
            return ResultJson.error(err);
        }

        MemberFamily memberFamilyDb = memberFamilyService.getMemberFamilyById(memberFamily.getId());
        // 上传图片
        String errFile = userIcoUpload(file, tombFile, hometownFile, memberFamily);
        if (errFile != null){
            return ResultJson.error(errFile);
        }

        if (CheckTool.checkNull(memberFamily.getUserName())){
            memberFamily.setUserName(Constant.DefaultValue.UNKNOWN_NAME);
        }

        EntityTool.buildUpdBase(memberFamily, StpUtil.getLoginIdAsString());
        memberFamilyService.updateById(memberFamily);

        // 清理图片
        delUserIco(memberFamilyDb, file, tombFile, hometownFile);

        return ResultJson.success();
    }

    /**
     * 查询用户的社交关系，家人和其他的人员都会查询出来
     * @param id 当前级别的用户主键，{@link MemberFamily#getId()}
     * @return
     */
    @PostMapping("/getSocialConnectionAll")
    public ResultJson getSocialConnectionAll(String id){
        if (CheckTool.checkNull(id)){
            // 未传则查询当前登录用户
            id = StpUtil.getLoginIdAsString();
        }
        String userId = StpUtil.getLoginIdAsString();

        List<MemberFamilyVo> allList = memberFamilyService.getSocialConnectionAll(id, userId);
        // for (MemberFamilyVo memberFamilyVo : allList){
        //     if (Constant.DefaultValue.UNKNOWN_NAME.equals(memberFamilyVo.getUserName())){
        //         memberFamilyVo.setUserName(Constant.DefaultValue.UNKNOWN);
        //     }
        // }

        return ResultJson.success(allList);
    }

    /**
     * 获取当前用户的家庭成员，注意，不会进行分页，因为家庭成员不会特别多
     * 只查询家庭成员，不会查询其他的人
     * @param excluding 是否包含当前登录用户，默认包含，true 包含， false 不包含
     * @return
     */
    @GetMapping("/getMemberFamilyAll")
    public ResultJson getMemberFamilyAll(Boolean excluding){
        if (excluding == null){
            excluding = true;
        }

        String userId = StpUtil.getLoginIdAsString();
        // 查询自己，id和社交关系的id一样
        List<MemberFamilyVo> list = new ArrayList<>();
        if (excluding){
            MemberFamily user = memberFamilyService.getMemberFamilyById(userId);
            MemberFamilyVo memberFamilyVo = BeanUtil.copyProperties(user, MemberFamilyVo.class);
            list.add(memberFamilyVo);
        }



        List<MemberFamilyVo> memberFamilyVoList = memberFamilyService.getMemberFamilyByUserId(userId);
        if (CollUtil.isNotEmpty(memberFamilyVoList)){
            list.addAll(memberFamilyVoList);
        }
        return ResultJson.success(list);
    }

    /**
     * 根据成员主键删除成员信息
     * @param id 成员表ID
     * @param password 验证密码，加密的
     * @param joinId 关系表ID
     * @return
     */
    @PostMapping("/delMemberFamilyById")
    @ApiIdempotent
    public ResultJson delMemberFamilyById(String id, String joinId, String password){
        if (CheckTool.checkNull(id, joinId)){
            return ResultJson.errorIllegal();
        }
        if (id.equals(StpUtil.getLoginIdAsString())){
            return ResultJson.error("该用户不允许删除");
        }

        // try {
        //     DES des = SecureUtil.des(loginPasswordKey.getBytes(Constant.Encoded.UTF));
        //     password = des.decryptStr(password);
        // } catch (Exception e) {
        //     log.error("[删除家庭用户] 解密密码错误,密码：{}", password);
        //     return ResultJson.error(ConstantMsg.ERROR_MSG_ILLEGAL_REQUEST);
        // }
        //
        // SaSession session = StpUtil.getSession(true);
        // User user = session.getModel(CacheKey.SaTokenSession.SESSION_KEY_USER, User.class);
        // // todo 应该进行加密，但这小系统不做复杂，防止忘记密码的事情
        // // String passwordOld = SaSecureUtil.md5BySalt(old, user.getSalt());
        // String passwordOld = password;
        // if (!user.getPassword().equals(passwordOld)){
        //     return ResultJson.error("密码错误");
        // }
        // todo 增加安全措施，不允许多次测试密码

        List<Join> joinList = joinService.getJoinBySourceId(id);
        if (CollUtil.isNotEmpty(joinList)){
            return ResultJson.error("该成员下面绑定有其他关系人，请先删除关系人后才能删除");
        }
        MemberFamily memberFamily = memberFamilyService.getMemberFamilyById(id);
        if (memberFamily == null){
            return ResultJson.errorPram();
        }
        if (memberFamily.getId().equals(StpUtil.getLoginIdAsString())){
            return ResultJson.error("主用户不允许删除");
        }

        memberFamilyService.delMemberFamilyById(id, joinId, StpUtil.getLoginIdAsString());

        // 删除用户头像
        // 删除陵墓照片
        // 删除老家照片
        // 创建一个空的文件，用来过验证
        MultipartFile multipartFile = getMultipartFile();
        delUserIco(memberFamily, multipartFile, multipartFile, multipartFile);
        // 删除用户的照片
        List<UploadFile> uploadFileList = uploadFileService.getUploadFileByBindingIdNotTemp(id);
        if (CollUtil.isNotEmpty(uploadFileList)){
            for (UploadFile uploadFile : uploadFileList){
                // 设置为临时文件，延迟交给定时器去删除。当前的这个删除操作并不优雅，可以批量操作
                uploadFile.setTempFile(Constant.TempFile.TEMP);
                uploadFileService.updateById(uploadFile);
            }
        }

        return ResultJson.success();
    }

    /**
     * 获取陵墓信息
     * @param page 分页参数
     * @return
     */
    @PostMapping("/getTombListPage")
    public ResultJson getTombListPage(Page page){
        String userId = StpUtil.getLoginIdAsString();
        return ResultJson.success(memberFamilyService.getTombListPage(page, userId));
    }

    /**
     * 获取当前用户树
     * @return
     */
    @GetMapping("/getMemberFamilyTree")
    public ResultJson getMemberFamilyTree(){
        String userId = StpUtil.getLoginIdAsString();
        List<MemberFamilyTree> tree = getTree(userId);
        return ResultJson.success(tree);
    }

    /**
     * 构建生成子节点树
     * @param tree 当前节点
     * @param list 全部节点
     */
    private void getChild(MemberFamilyTree tree, List<MemberFamilyTree> list){
        List<MemberFamilyTree> childList = list.stream().filter(obj -> tree.getTargetId().equals(obj.getSourceId())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(childList)){
            tree.setChildren(childList);

            for (MemberFamilyTree familyTree : childList){
                getChild(familyTree, list);
            }
        }
    }

    /**
     * 头像上传
     * @param multipartFile 上传的头像文件
     * @param memberFamily 成员信息
     * @return
     */
    private String saveMemberFamilyCover(MultipartFile multipartFile, MemberFamily memberFamily){
        String originalFilename = multipartFile.getOriginalFilename();
        if (CheckTool.checkNull(originalFilename)){
            return "获取头像文件名失败";
        }
        String suffix = FileUtil.getSuffix(originalFilename).toLowerCase();
        if (CheckTool.checkNull(suffix)){
            // 检查特殊情况下的文件名不符合
            return "非法上传头像图片名，不支持的后缀";
        }
        if (uploadImageTypeList != null){
            if (!uploadImageTypeList.contains(suffix)){
                return "上传头像图片类型不支持";
            }
        }
        if (multipartFile.getSize() > uploadImageMaxLength){
            return "上传头像图片超过限定大小";
        }

        String path = String.format(ConstantPath.Path.MEMBER_FAMILY_ICO, basePath, StpUtil.getLoginIdAsString(), IdTool.getId(), suffix);
        File toFile = new File(path);
        // 上传路径
        if (!FileUtil.exist(toFile)){
            FileUtil.touch(toFile);
        }

        try {
            multipartFile.transferTo(toFile);
        } catch (IOException e) {
            log.error("图片上传失败", e);
            return "头像图片上传失败";
        }

        // 只保存相对路径
        String replacePath = path.replace(basePath, "");
        memberFamily.setIcoPath(replacePath);
        return null;
    }

    /**
     * 保存陵墓照片
     * @param multipartFile 上传的图片
     * @param memberFamily 文件信息
     * @return
     */
    private String saveTomb(MultipartFile multipartFile, MemberFamily memberFamily){
        String originalFilename = multipartFile.getOriginalFilename();
        if (CheckTool.checkNull(originalFilename)){
            return "获取陵墓照片文件名失败";
        }
        String suffix = FileUtil.getSuffix(originalFilename).toLowerCase();
        if (CheckTool.checkNull(suffix)){
            // 检查特殊情况下的文件名不符合
            return "非法上传陵墓图片名，不支持的后缀";
        }
        if (uploadImageTypeList != null){
            if (!uploadImageTypeList.contains(suffix)){
                return "上传陵墓图片类型不支持";
            }
        }
        if (multipartFile.getSize() > uploadImageMaxLength){
            return "上传陵墓图片超过限定大小";
        }

        String path = String.format(ConstantPath.Path.MEMBER_FAMILY_TOMB_ICO, basePath, StpUtil.getLoginIdAsString(), IdTool.getId(), suffix);
        File toFile = new File(path);
        // 上传路径
        if (!FileUtil.exist(toFile)){
            FileUtil.touch(toFile);
        }

        try {
            multipartFile.transferTo(toFile);
        } catch (IOException e) {
            log.error("图片上传失败", e);
            return "陵墓图片上传失败";
        }

        // 只保存相对路径
        String replacePath = path.replace(basePath, "");
        memberFamily.setTombIcoPath(replacePath);
        return null;
    }

    /**
     * 保存老家照片
     * @param multipartFile 上传的图片
     * @param memberFamily 文件信息
     * @return
     */
    private String saveHometown(MultipartFile multipartFile, MemberFamily memberFamily){
        String originalFilename = multipartFile.getOriginalFilename();
        if (CheckTool.checkNull(originalFilename)){
            return "获取老家照片文件名失败";
        }
        String suffix = FileUtil.getSuffix(originalFilename).toLowerCase();
        if (CheckTool.checkNull(suffix)){
            // 检查特殊情况下的文件名不符合
            return "非法上传老家图片名，不支持的后缀";
        }
        if (uploadImageTypeList != null){
            if (!uploadImageTypeList.contains(suffix)){
                return "上传老家图片类型不支持";
            }
        }
        if (multipartFile.getSize() > uploadImageMaxLength){
            return "上传老家图片超过限定大小";
        }

        String path = String.format(ConstantPath.Path.MEMBER_FAMILY_HOMETOWN_ICO, basePath, StpUtil.getLoginIdAsString(), IdTool.getId(), suffix);
        File toFile = new File(path);
        // 上传路径
        if (!FileUtil.exist(toFile)){
            FileUtil.touch(toFile);
        }

        try {
            multipartFile.transferTo(toFile);
        } catch (IOException e) {
            log.error("图片上传失败", e);
            return "老家图片上传失败";
        }

        // 只保存相对路径
        String replacePath = path.replace(basePath, "");
        memberFamily.setHometownIcoPath(replacePath);
        return null;
    }

    /**
     * 检查成员信息
     * @param memberFamily 成员信息
     * @return 非null则有问题
     */
    private String checkMemberFamily(MemberFamily memberFamily){
        // 判断是否已经保存过
        if (!Constant.DefaultValue.UNKNOWN_NAME.equals(memberFamily.getUserName())){
            MemberFamily memberFamilyDb = memberFamilyService.getMemberFamilyRepeatQuery(memberFamily.getId(), StpUtil.getLoginIdAsString(), memberFamily.getUserName());
            if (memberFamilyDb != null){
                // 后面如果出现家族多个同姓名的，可以考虑加上身份证的验证，但现在的话，先不考虑，否则会导致一些问题，因为设计的时候就是单独一个姓名，这个概率还是比较低的
                return "该成员已添加，不需要重复添加";
            }
            MemberFamily db = memberFamilyService.getMemberFamilyByIdCard(memberFamily.getId(), StpUtil.getLoginIdAsString(), memberFamily.getIdCard());
            if (db != null){
                return "身份证已使用，请确认是否重复添加人员";
            }
        }

        if (memberFamily.getBirthdayTips() == null){
            memberFamily.setBirthdayTips(Constant.YesOrNo.NO);
        } else {
            if (memberFamily.getBeforeBirthday() != null){
                if (memberFamily.getBeforeBirthday() > 31){
                    return "生日提醒应该在30天内";
                } else if (memberFamily.getBeforeBirthday() < 1){
                    return "生日提醒时间无效";
                }
            }
        }
        if (memberFamily.getSort() == null){
            memberFamily.setSort(Constant.DefaultValue.SORT);
        }
        if (!CheckTool.checkNull(memberFamily.getResidentialAddress())){
            if (CheckTool.checkNull(memberFamily.getResidentialAddressHometown())){
                memberFamily.setResidentialAddressHometown(memberFamily.getResidentialAddress());
            }
        }

        return null;
    }

    /**
     * 补充用户的身份证数据
     * @param memberFamily 用户
     * @return 非null则有问题
     */
    private String idCardSupplement(MemberFamily memberFamily){
        // 身份证获取
        if (!IdcardUtil.isValidCard(memberFamily.getIdCard())){
            return null;
        }

        boolean validCard = IdcardUtil.isValidCard(memberFamily.getIdCard());
        if (!validCard){
            return "无效的身份证";
        }

        // 性别
        int genderByIdCard = IdcardUtil.getGenderByIdCard(memberFamily.getIdCard());
        memberFamily.setSex(genderByIdCard);

        // 只有在没有输入生日的情况下才进行生日的检测
        if (!CheckTool.checkNull(memberFamily.getBirth())){
            return null;
        }

        // 生日，从身份证中获取的生日
        Date birth = IdcardUtil.getBirthDate(memberFamily.getIdCard());
        // 出生年月转阴历，中国一般使用阴历来计算生日
        memberFamily.setLunarCalendar(Constant.Calendar.LUNAR_CALENDAR);
        // 2023年2月26日22:17:42 暂不考虑这种转换，发现大部分不需要转换，还是按照这个时间生日，但是第二年这个时间用阴历生日
        // LunarVo lunarVo = DateTool.toLunar(birth);
        memberFamily.setBirth(DateUtil.format(birth, DatePattern.NORM_DATE_PATTERN));
        // memberFamily.setBirth(lunarVo.getYearLunar() + "-" + lunarVo.getMonthLunar() + "-" + lunarVo.getDayLunar());

        // 如果真实生日日期没填，就从身份证中获取，否则取页面输入的，todo 暂时不考虑特殊日期的处理，比如2月29日
        if (memberFamily.getBirthdayTime() == null){
            // memberFamily.setBirthdayTime(lunarVo.getMonthLunar() + "-" + lunarVo.getDayLunar());
            memberFamily.setBirthdayTime((DateUtil.month(birth) + 1) + "-" + DateUtil.dayOfMonth(birth));
        }

        return null;
    }


    /**
     * 关系校验，大部分的数据都注解校验了
     * @param join 关系
     * @return 非null则有异常
     */
    private String checkJoin(Join join){
        if (CheckTool.checkNull(join.getSourceId())){
            return "必须指定关联人";
        }

        return null;
    }

    /**
     * 删除旧图片
     * @param memberFamilyDb 历史用户信息
     * @param file 头像图片
     * @param tombFile 陵墓图片
     * @param hometownFile 老家图片
     * @return
     */
    private void delUserIco(MemberFamily memberFamilyDb, MultipartFile file, MultipartFile tombFile, MultipartFile hometownFile){
        // 删除旧的头像文件
        if (file != null){
            String icoPath = memberFamilyDb.getIcoPath();
            if (!CheckTool.checkNull(icoPath)){
                // 做容错措施，如果是目录，不进行操作，数据非常重要，一定要多检查
                if (FileUtil.isFile(basePath + icoPath)){
                    FileUtil.del(basePath + icoPath);
                } else {
                    log.error("要删除的是数据是目录，跳过该删除操作：{}", basePath + icoPath);
                }
            }
        }
        // 删除陵墓照片
        if (tombFile != null){
            String icoPath = memberFamilyDb.getTombIcoPath();
            if (!CheckTool.checkNull(icoPath)){
                // 做容错措施，如果是目录，不进行操作，数据非常重要，一定要多检查
                if (FileUtil.isFile(basePath + icoPath)){
                    FileUtil.del(basePath + icoPath);
                } else {
                    log.error("要删除的是数据是目录，跳过该删除操作：{}", basePath + icoPath);
                }
            }
        }
        // 删除老家照片
        if (hometownFile != null){
            String icoPath = memberFamilyDb.getHometownIcoPath();
            if (!CheckTool.checkNull(icoPath)){
                // 做容错措施，如果是目录，不进行操作，数据非常重要，一定要多检查
                if (FileUtil.isFile(basePath + icoPath)){
                    FileUtil.del(basePath + icoPath);
                } else {
                    log.error("要删除的是数据是目录，跳过该删除操作：{}", basePath + icoPath);
                }
            }
        }
    }

    /**
     * 图片等上传
     * @param file 头像图片
     * @param tombFile 陵墓图片
     * @param hometownFile 老家图片
     * @param memberFamily 用户信息
     * @return
     */
    private String userIcoUpload(MultipartFile file, MultipartFile tombFile, MultipartFile hometownFile, MemberFamily memberFamily){
        // 上传头像
        if (file != null){
            String errFile = saveMemberFamilyCover(file, memberFamily);
            if (errFile != null){
                return errFile;
            }
        }
        // 陵墓图片
        if (tombFile != null){
            String errFile = saveTomb(tombFile, memberFamily);
            if (errFile != null){
                return errFile;
            }
        }
        // 老家照片
        if (hometownFile != null){
            String errFile = saveHometown(hometownFile, memberFamily);
            if (errFile != null){
                return errFile;
            }
        }

        return null;
    }

    /**
     * 构建一个空的 上传文件类，用来过检测
     * @return
     */
    private MultipartFile getMultipartFile(){
        return new MultipartFile() {
            @Override
            public String getName() {
                return null;
            }

            @Override
            public String getOriginalFilename() {
                return null;
            }

            @Override
            public String getContentType() {
                return null;
            }

            @Override
            public boolean isEmpty() {
                return false;
            }

            @Override
            public long getSize() {
                return 0;
            }

            @Override
            public byte[] getBytes() throws IOException {
                return new byte[0];
            }

            @Override
            public InputStream getInputStream() throws IOException {
                return null;
            }

            @Override
            public void transferTo(File dest) throws IOException, IllegalStateException {

            }
        };
    }

    /**
     * 获取当前登录人的数据
     * @return
     */
    private MemberFamilyVo getMemberFamilyThis(){
        MemberFamily memberFamily = memberFamilyService.getMemberFamilyById(StpUtil.getLoginIdAsString());
        MemberFamilyVo memberFamilyVo = BeanUtil.copyProperties(memberFamily, MemberFamilyVo.class);
        memberFamilyVo.setCall("登录人");
        memberFamilyVo.setDataExplain("无数据");
        memberFamilyVo.setConnectionTypeName("登录人");
        return memberFamilyVo;
    }

    /**
     * 获取指定用户的用户数
     * @param userId 用户ID
     * @return
     */
    private List<MemberFamilyTree> getTree(String userId){
        MemberFamily memberFamily = memberFamilyService.getMemberFamilyById(userId);
        MemberFamilyTree root = BeanUtil.copyProperties(memberFamily, MemberFamilyTree.class);
        root.setSourceId(userId);
        root.setTargetId(userId);
        // 根节点
        List<MemberFamilyTree> list = new ArrayList<>();

        List<MemberFamilyTree> treeList = memberFamilyService.getMemberFamilyJoinByUserIdAll(userId);
        if (CollUtil.isNotEmpty(treeList)){
            list.addAll(treeList);
        }

        // 处理不知道名字的
        // for (MemberFamilyTree memberFamilyTree : treeList){
        //     if (Constant.DefaultValue.UNKNOWN_NAME.equals(memberFamilyTree.getUserName())){
        //         memberFamilyTree.setUserName(Constant.DefaultValue.UNKNOWN);
        //     }
        // }

        getChild(root, list);

        List<MemberFamilyTree> resultList = new ArrayList<>();
        resultList.add(root);
        return resultList;
    }

    /**
     * 删除自身的数据
     * @param tree 全部树
     * @param userId 用户ID
     */
    private void delThisNode(List<MemberFamilyTree> tree, String userId){
        if (CollUtil.isEmpty(tree)){
            return;
        }
        Iterator<MemberFamilyTree> iterator = tree.iterator();
        while (iterator.hasNext()) {
            MemberFamilyTree child = iterator.next();
            if (child.getId().equals(userId)) {
                // 如果找到了目标节点，直接删除该节点
                iterator.remove();
                return;
            } else {
                // 否则递归删除子树中的目标节点
                delThisNode(child.getChildren(), userId);
            }
        }
    }

    /**
     * 遍历可迁移的用户
     * @param userList 存储最终迁移的用户
     * @param tree 要遍历的树
     */
    private void getTransferUser(List<MemberFamilyTree> userList, List<MemberFamilyTree> tree){
        for (MemberFamilyTree familyTree : tree) {
            userList.add(familyTree);
            if (CollUtil.isNotEmpty(familyTree.getChildren())){
                getTransferUser(userList, familyTree.getChildren());
            }
        }
    }
}
